home *** CD-ROM | disk | FTP | other *** search
- /* User subroutines for AX.25 */
- #include "global.h"
- #include "mbuf.h"
- #include "timer.h"
- #include "iface.h"
- #include "ax25.h"
- #include "lapb.h"
- #include <ctype.h>
-
- /* Open an AX.25 connection */
- struct ax25_cb *
- open_ax25(addr,window,r_upcall,t_upcall,s_upcall,iface,user)
- struct ax25 *addr; /* Addresses */
- int16 window; /* Window size in bytes */
- void (*r_upcall)(); /* Receiver upcall handler */
- void (*t_upcall)(); /* Transmitter upcall handler */
- void (*s_upcall)(); /* State-change upcall handler */
- struct interface *iface; /* Hardware interface structure */
- char *user; /* User linkage area */
- {
- register struct ax25_cb *axp;
- struct ax25_call *axc;
- struct ax25_cb *cr_ax25();
- void lapbstate();
-
- if((axc = find_axcall(ax25_excl,&addr->dest)) != NULLAXCALL &&
- ((axc->flags & MULTI_IF) || axc->interface == iface))
- return NULLAX25;
- if((axp = cr_ax25(&addr->dest,&addr->source)) == NULLAX25)
- return NULLAX25;
- ASSIGN(axp->addr,*addr);
- if(addr->ndigis != 0){
- axp->t1.start *= (addr->ndigis + 1);
- axp->t2.start *= (addr->ndigis + 1);
- /*axp->t3.start *= (addr->ndigis + 1);
- axp->t4.start *= (addr->ndigis + 1);*/
- }
- axp->window = window;
- axp->r_upcall = r_upcall;
- axp->t_upcall = t_upcall;
- axp->s_upcall = s_upcall;
- axp->interface = iface;
- axp->user = user;
-
- if (axp->state == DISCONNECTED){
- /* Don't send anything if the connection already exists */
- lapbstate(axp,SETUP,LAPBNOMS);
- sendctl(axp,COMMAND,SABM|PF);
- }
- return axp;
- }
-
- /* Send data on an AX.25 connection. Caller must provide PID */
- int
- send_ax25(axp,bp)
- struct ax25_cb *axp;
- struct mbuf *bp;
- {
- if(axp == NULLAX25 || bp == NULLBUF || axp->fin){
- free_p(bp);
- return -1;
- }
- enqueue(&axp->txq,bp);
- return lapb_output(axp);
- }
-
- /* Send data on an AX.25 connection, creating packets sized "paclen" */
- sendp_ax25(axp,bp,pid)
- register struct ax25_cb *axp;
- struct mbuf *bp;
- char pid;
- {
- register struct mbuf *tbp;
- int16 bsize;
-
- if(axp == NULLAX25 || bp == NULLBUF)
- return;
- bsize = len_mbuf(bp);
- while(bsize != 0){
- if (bsize <= axp->paclen) {
- if((tbp = pushdown(bp,1)) == NULLBUF) {/* make space for PID */
- free_p(bp);
- break; /* out of memory! */
- }
- bsize = 0;
- } else {
- /* Allocate buffer, allowing space for PID */
- if((tbp = alloc_mbuf(axp->paclen + 1)) == NULLBUF) {
- free_p(bp);
- break; /* out of memory! */
- }
- tbp->cnt = 1 + pullup(&bp,tbp->data + 1,axp->paclen);
- bsize -= axp->paclen;
- }
- *tbp->data = pid;
- send_ax25(axp,tbp);
- }
- }
-
- /* Send UI frames to an AX.25-type iface, creating packets sized "paclen" */
- sendui_ax25(ifp,addr,bp,pid)
- struct interface *ifp;
- struct ax25 *addr;
- struct mbuf *bp;
- char pid;
- {
- register struct mbuf *tbp;
- int16 bsize;
- extern int16 paclen;
-
- if(ifp == NULLIF || bp == NULLBUF)
- return;
- bsize = len_mbuf(bp);
- while(bsize != 0){
- if (bsize <= paclen) {
- if((tbp = pushdown(bp,1)) == NULLBUF) {/* make space for PID */
- free_p(bp);
- break; /* out of memory! */
- }
- bsize = 0;
- } else {
- /* Allocate buffer, allowing space for PID */
- if((tbp = alloc_mbuf(paclen + 1)) == NULLBUF) {
- free_p(bp);
- break; /* out of memory! */
- }
- tbp->cnt = 1 + pullup(&bp,tbp->data + 1,paclen);
- bsize -= paclen;
- }
- *tbp->data = pid;
- senduiframe(ifp,addr,tbp);
- }
- }
-
- /* Receive incoming data on an AX.25 connection */
- struct mbuf *
- recv_ax25(axp,cnt)
- register struct ax25_cb *axp;
- int16 cnt;
- {
- struct mbuf *bp;
- unsigned rxqlen;
-
- if(axp->rxq == NULLBUF)
- return NULLBUF;
-
- if ((rxqlen = len_mbuf(axp->rxq)) <= cnt || cnt == 0){
- bp = axp->rxq;
- axp->rxq = NULLBUF;
- cnt = rxqlen;
- } else {
- if ((bp = alloc_mbuf(cnt)) == NULLBUF)
- return NULLBUF;
-
- cnt = bp->cnt = pullup(&axp->rxq,bp->data,cnt);
- }
- /* If this has un-busied us, send a RR to reopen the window */
- if(rxqlen >= axp->window && (rxqlen - cnt) < axp->window)
- sendctl(axp,RESPONSE,RR);
- return bp;
- }
-
- /* Get a line of text from an AX.25 connection (up to \r) */
- /* The textline may span multiple incoming packets, so NULLBUF is returned */
- /* as long as the line is incomplete (and it is saved) */
- struct mbuf *
- recvl_ax25(axp,cnt)
- register struct ax25_cb *axp;
- int16 cnt;
- {
- struct mbuf *bp;
- unsigned rxqlen;
-
- if(axp->rxq == NULLBUF)
- return NULLBUF;
-
- rxqlen = len_mbuf(axp->rxq);
-
- if ((bp = pullline(&axp->rxq,cnt)) != NULLBUF){
- /* If this has un-busied us, send a RR to reopen the window */
- if(rxqlen >= axp->window && (rxqlen - bp->cnt) < axp->window)
- sendctl(axp,RESPONSE,RR);
- }
- return bp;
- }
-
- /* "Gracefully Close" an AX.25 connection */
- close_ax25(axp)
- struct ax25_cb *axp;
- {
- axp->fin = YES; /* set FIN flag */
- if (axp->txq == NULLBUF && /* no outstanding frames? */
- axp->state != DISCPENDING) /* not already disconnecting? */
- disc_ax25(axp); /* start disconnecting now */
- }
-
- /* Close an AX.25 connection */
- disc_ax25(axp)
- struct ax25_cb *axp;
- {
- void lapbstate();
-
- switch (axp->state)
- {
- case DISCONNECTED:
- break; /* Ignored */
- case DISCPENDING: /* was pending, just drop it */
- lapbstate(axp,DISCONNECTED,LAPBDISC);
- del_ax25(axp);
- break;
- case CONNECTED: /* was connected, full retries */
- lapbstate(axp,DISCPENDING,LAPBNOMS);
- sendctl(axp,COMMAND,DISC|PF);
- break;
- default: /* SETUP */
- lapbstate(axp,DISCPENDING,LAPBNOMS);
- axp->retries = axp->n2 - 2; /* try 3 times only */
- sendctl(axp,COMMAND,DISC|PF);
- break;
- }
- }
-
- /* Verify that axp points to a valid ax25 control block */
- ax25val(axp)
- struct ax25_cb *axp;
- {
- register struct ax25_cb *axp1;
- register int i;
-
- if(axp == NULLAX25)
- return 0; /* Null pointer can't be valid */
- for(i=0; i < NHASH; i++)
- for(axp1 = ax25_cb[i];axp1 != NULLAX25; axp1 = axp1->next)
- if(axp1 == axp)
- return 1;
- return 0;
- }
-
- /* Force a retransmission */
- kick_ax25(axp)
- struct ax25_cb *axp;
- {
- void recover();
-
- if(!ax25val(axp))
- return -1;
- recover((int *)axp);
- return 0;
- }
-
- /* Abruptly terminate an AX.25 connection */
- reset_ax25(axp)
- struct ax25_cb *axp;
- {
- void lapbstate();
-
- lapbstate(axp,DISCONNECTED,LAPBNOMS);
- del_ax25(axp);
- }
-